package com.liunian.algorithmstudy.backtracking.hard;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class SolveNQueens51 {

	/**
	 按照国际象棋的规则，皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
	 n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上，并且使皇后彼此之间不能相互攻击。
	 给你一个整数 n ，返回所有不同的 n 皇后问题 的解决方案。
	 每一种解法包含一个不同的 n 皇后问题 的棋子放置方案，该方案中 'Q' 和 '.' 分别代表了皇后和空位。

	 示例 1：
	 输入：n = 4
	 输出：[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
	 解释：如上图所示，4 皇后问题存在两个不同的解法。

	 示例 2：
	 输入：n = 1
	 输出：[["Q"]]
	 */
	List<List<String>> res = new ArrayList<>();
	public List<List<String>> solveNQueens(int n) {
		char[][] cherryBoard = new char[n][n];
		for (int i = 0; i < n; i++) {
			Arrays.fill(cherryBoard[i], '.');
		}
		backTracking(cherryBoard, n, 0);
		return res;
	}

	private void backTracking(char[][] cherryBoard, int n, int index) {
		if (index == n) {
			res.add(new ArrayList<>(charsToArray(cherryBoard, n)));
			return;
		}
		for (int i = 0; i < n; i++) {
			if (isValid(cherryBoard, index, i)) {
				cherryBoard[index][i] = 'Q';
				backTracking(cherryBoard, n, index + 1);
				cherryBoard[index][i] = '.';
			}
		}
	}

	private List<String> charsToArray(char[][] cherryBoard, int n) {
		List<String> path = new ArrayList<>();
		for (int i = 0; i < n; i++) {
			path.add(String.copyValueOf(cherryBoard[i]));
		}
		return path;
	}

	private boolean isValid(char[][] cherryBoard, int row, int col) {
		for (int i = 0; i < row; i++) {
			if (cherryBoard[i][col] == 'Q') {
				return false;
			}
		}
		for (int i = 0; i < col; i++) {
			if (cherryBoard[row][i] == 'Q') {
				return false;
			}
		}
		for (int i = row, j = col; i >= 0 && j >= 0; i--, j--) {
			if (cherryBoard[i][j] == 'Q') {
				return false;
			}
		}
		for (int i = row, j = col; i >= 0 && j < cherryBoard[0].length; i--, j++) {
			if (cherryBoard[i][j] == 'Q') {
				return false;
			}
		}
		return true;
	}

	public static void main(String[] args) {
		SolveNQueens51 q = new SolveNQueens51();
		System.out.println(q.solveNQueens(1));
	}

}
